{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-10-19T03:08:23.403657Z",
     "start_time": "2020-10-19T03:08:23.399582Z"
    }
   },
   "outputs": [],
   "source": [
    "import tensorflow.compat.v1 as tf\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn import datasets\n",
    "tf.disable_v2_behavior()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-10-19T03:08:26.812132Z",
     "start_time": "2020-10-19T03:08:26.797847Z"
    }
   },
   "outputs": [],
   "source": [
    "class Autoencoder:\n",
    "    def __init__(self,input_di,hidden_dim,epoch=250,learning_rate=0.001):\n",
    "        self.epoch=epoch\n",
    "        self.learning_rate=learning_rate\n",
    "        \n",
    "        x=tf.placeholder(dtype=tf.float32,shape=[None,input_dim])\n",
    "        \n",
    "        with tf.name_scope('encode'):\n",
    "            weights=tf.Variable(tf.random_normal([input_dim,hidden_dim],dtype=tf.float32)\n",
    "                               ,name='weights')\n",
    "            biases=tf.Variable(tf.zeros([hidden_dim]),name='biases')\n",
    "            encoded=tf.nn.tanh(tf.matmul(x,weights)+biases)\n",
    "        with tf.name_scope('decode'):\n",
    "            weights=tf.Variable(tf.random_normal([input_dim,hidden_dim],dtype=tf.float32)\n",
    "                               ,name='weights')\n",
    "            biases=tf.Variable(tf.zeros([hidden_dim]),name='biases')\n",
    "            decoded=tf.matmul(encoded,weights)+biases\n",
    "            \n",
    "        self.x=x\n",
    "        self.encoded=encoded\n",
    "        self.decoded=decoded\n",
    "        \n",
    "        self.loss=tf.sqrt(tf.reduce_mean(tf.square(tf.subtract(self.x,self.decoded))))\n",
    "        self.train_op=tf.train.RMSPropOptimizer(self.learning_rate).minimize(self.loss)\n",
    "        self.saver=tf.train.Saver()\n",
    "    \n",
    "    def train(self,data):\n",
    "        num_samples=len(data)\n",
    "        with tf.Session() as sess:\n",
    "            sess.run(tf.global_variables_initializer())\n",
    "            for i in range(self.epoch):\n",
    "                for j in range(num_samples):\n",
    "                    l,_= sess.run([sself.loss,self.train_op],feed_dict={self.x:[data[j]]})\n",
    "                if i % 10 == 0:\n",
    "                    print('epoch {0} : loss={1}'.format(i,1))\n",
    "                    self.saver.save(sess,'./model.ckpt')\n",
    "            self.saver.save(sess,'./model.ckpt')\n",
    "    \n",
    "    def test(self,data):\n",
    "        with tf.Session() as sess:\n",
    "            self.saver.restore(sess,'./model.ckpt')\n",
    "            hidden,reconstructed=sess.run([self.encoded,self.decoded],feed_dict={self.x:data})\n",
    "        print('input',data)\n",
    "        print('compressed',hidden)\n",
    "        print('reconstructed',reconstructed)\n",
    "        return reconstructed\n",
    "            \n",
    "            \n",
    "                               "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "Dimensions must be equal, but are 1 and 4 for '{{node decode_1/MatMul}} = MatMul[T=DT_FLOAT, transpose_a=false, transpose_b=false](encode_1/Tanh, decode_1/weights/read)' with input shapes: [?,1], [4,1].",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mInvalidArgumentError\u001b[0m                   Traceback (most recent call last)",
      "\u001b[0;32m~/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/framework/ops.py\u001b[0m in \u001b[0;36m_create_c_op\u001b[0;34m(graph, node_def, inputs, control_inputs, op_def)\u001b[0m\n\u001b[1;32m   1653\u001b[0m   \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1654\u001b[0;31m     \u001b[0mc_op\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpywrap_tf_session\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTF_FinishOperation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mop_desc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1655\u001b[0m   \u001b[0;32mexcept\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mInvalidArgumentError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mInvalidArgumentError\u001b[0m: Dimensions must be equal, but are 1 and 4 for '{{node decode_1/MatMul}} = MatMul[T=DT_FLOAT, transpose_a=false, transpose_b=false](encode_1/Tanh, decode_1/weights/read)' with input shapes: [?,1], [4,1].",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[0;31mValueError\u001b[0m                             Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-9-b869c5ba244f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdatasets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mload_iris\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0minput_dim\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mae\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mAutoencoder\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput_dim\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mhidden_dim\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      5\u001b[0m \u001b[0mae\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrain\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m \u001b[0mae\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m8\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-8-0400f1bdbf0b>\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, input_di, hidden_dim, epoch, learning_rate)\u001b[0m\n\u001b[1;32m     15\u001b[0m                                ,name='weights')\n\u001b[1;32m     16\u001b[0m             \u001b[0mbiases\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mVariable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mhidden_dim\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'biases'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 17\u001b[0;31m             \u001b[0mdecoded\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmatmul\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mencoded\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mweights\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0mbiases\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     19\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/util/dispatch.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m    178\u001b[0m     \u001b[0;34m\"\"\"Call target, and fall back on dispatchers if there is a TypeError.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    179\u001b[0m     \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 180\u001b[0;31m       \u001b[0;32mreturn\u001b[0m \u001b[0mtarget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    181\u001b[0m     \u001b[0;32mexcept\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mTypeError\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    182\u001b[0m       \u001b[0;31m# Note: convert_to_eager_tensor currently raises a ValueError, not a\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/ops/math_ops.py\u001b[0m in \u001b[0;36mmatmul\u001b[0;34m(a, b, transpose_a, transpose_b, adjoint_a, adjoint_b, a_is_sparse, b_is_sparse, name)\u001b[0m\n\u001b[1;32m   2981\u001b[0m       \u001b[0;32mreturn\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2982\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2983\u001b[0;31m       return gen_math_ops.mat_mul(\n\u001b[0m\u001b[1;32m   2984\u001b[0m           a, b, transpose_a=transpose_a, transpose_b=transpose_b, name=name)\n\u001b[1;32m   2985\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/ops/gen_math_ops.py\u001b[0m in \u001b[0;36mmat_mul\u001b[0;34m(a, b, transpose_a, transpose_b, name)\u001b[0m\n\u001b[1;32m   5583\u001b[0m     \u001b[0mtranspose_b\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   5584\u001b[0m   \u001b[0mtranspose_b\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_execute\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmake_bool\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtranspose_b\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"transpose_b\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 5585\u001b[0;31m   _, _, _op, _outputs = _op_def_library._apply_op_helper(\n\u001b[0m\u001b[1;32m   5586\u001b[0m         \u001b[0;34m\"MatMul\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtranspose_a\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtranspose_a\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtranspose_b\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtranspose_b\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   5587\u001b[0m                   name=name)\n",
      "\u001b[0;32m~/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/framework/op_def_library.py\u001b[0m in \u001b[0;36m_apply_op_helper\u001b[0;34m(op_type_name, name, **keywords)\u001b[0m\n\u001b[1;32m    740\u001b[0m       \u001b[0;31m# Add Op to graph\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    741\u001b[0m       \u001b[0;31m# pylint: disable=protected-access\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 742\u001b[0;31m       op = g._create_op_internal(op_type_name, inputs, dtypes=None,\n\u001b[0m\u001b[1;32m    743\u001b[0m                                  \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mscope\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minput_types\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0minput_types\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    744\u001b[0m                                  attrs=attr_protos, op_def=op_def)\n",
      "\u001b[0;32m~/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/framework/ops.py\u001b[0m in \u001b[0;36m_create_op_internal\u001b[0;34m(self, op_type, inputs, dtypes, input_types, name, attrs, op_def, compute_device)\u001b[0m\n\u001b[1;32m   3317\u001b[0m     \u001b[0;31m# Session.run call cannot occur between creating and mutating the op.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   3318\u001b[0m     \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_mutation_lock\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3319\u001b[0;31m       ret = Operation(\n\u001b[0m\u001b[1;32m   3320\u001b[0m           \u001b[0mnode_def\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   3321\u001b[0m           \u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/framework/ops.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, node_def, g, inputs, output_types, control_inputs, input_types, original_op, op_def)\u001b[0m\n\u001b[1;32m   1814\u001b[0m       \u001b[0;32mif\u001b[0m \u001b[0mop_def\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1815\u001b[0m         \u001b[0mop_def\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_graph\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_op_def\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnode_def\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mop\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1816\u001b[0;31m       self._c_op = _create_c_op(self._graph, node_def, inputs,\n\u001b[0m\u001b[1;32m   1817\u001b[0m                                 control_input_ops, op_def)\n\u001b[1;32m   1818\u001b[0m       \u001b[0mname\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcompat\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mas_str\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnode_def\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/envs/mytf/lib/python3.8/site-packages/tensorflow/python/framework/ops.py\u001b[0m in \u001b[0;36m_create_c_op\u001b[0;34m(graph, node_def, inputs, control_inputs, op_def)\u001b[0m\n\u001b[1;32m   1655\u001b[0m   \u001b[0;32mexcept\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mInvalidArgumentError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1656\u001b[0m     \u001b[0;31m# Convert to ValueError for backwards compatibility.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1657\u001b[0;31m     \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1658\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1659\u001b[0m   \u001b[0;32mreturn\u001b[0m \u001b[0mc_op\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: Dimensions must be equal, but are 1 and 4 for '{{node decode_1/MatMul}} = MatMul[T=DT_FLOAT, transpose_a=false, transpose_b=false](encode_1/Tanh, decode_1/weights/read)' with input shapes: [?,1], [4,1]."
     ]
    }
   ],
   "source": [
    "hidden_dim=1\n",
    "data=datasets.load_iris().data\n",
    "input_dim=len(data[0])\n",
    "ae=Autoencoder(input_dim,hidden_dim)\n",
    "ae.train(data)\n",
    "ae.test([[8,4,6,2]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
